﻿#ifndef CPEPLUGINMANAGER_H
#define CPEPLUGINMANAGER_H

#include "pluginMetaData.h"
#include "cpepluginmanager_global.h"
#include <QObject>
#include <QPluginLoader>
#include <QVariant>
#include <QHash>
#include <QStringList>
#include <QDir>
#include <QString>

/**
 * @brief The CpePluginManager class CpeManager插件管理器类
 */
class CPEPLUGINMANAGER_EXPORT CpePluginManager : public QObject
{
    Q_OBJECT
public:
    /**
     * @brief getInstance   声明为单例类
     * @return              类实例指针
     */
    static CpePluginManager *getInstance()
    {
        if (m_pInstance == nullptr)
        {
            m_pInstance = new CpePluginManager();
        }
        return m_pInstance;
    }

    /**
     * @brief getPluginPath 加载所有插件
     */
    void loadAllPlugin();

    /**
     * @brief scanAllPlugin 扫描所有插件元数据
     */
    void scanAllPlugin();

    /**
     * @brief loadPlugin    加载某个插件
     * @param filepath      插件文件名
     */
    bool loadPlugin(const QString &strPluginName);

    /**
     * @brief startPlugin   执行某个插件的startPlugin方法
     * @param strPluginName 插件名称
     */
    void startPlugin(const QString &strPluginName);

    /**
     * @brief unloadAllPlugins  卸载所有插件
     */
    void unloadAllPlugins();

    /**
     * @brief getPath       由插件名字转路径
     * @param strPluginName 插件名称
     */
    QString getPath(const QString &strPluginName);

    /**
     * @brief unloadPlugin  卸载某个插件
     * @param strPluginName 插件名称
     */
    bool unloadPlugin(const QString &strPluginName);

    /**
     * @brief allPlugins    获取所有插件的名称
     */
    QStringList getAllPluginName();

    /**
     * @brief getAllPluginInfo  获取全部插件信息
     * @param name              插件名称
     * @param version           插件版本
     * @param descriptions      插件描述
     * @param authors           插件作者
     * @param types             插件类型
     * #param dependcies        插件依赖
     * @param loaders           插件Loader指针
     */
    void getAllPluginInfo(QHash<QString, QString> &name
                          , QHash<QString, QString> &version
                          , QHash<QString, QString> &descriptions
                          , QHash<QString, QString> &authors
                          , QHash<QString, bool> &types
                          , QHash<QString, QVariantList> &dependcies
                          , QStringList &loaders
                         );

    /**
    * @brief getPluginInterface 获取插件接口指针
    * @param strPluginName      插件名称
    */
    template<class T>
    T *getPluginInterface(const QString &strPluginName)
    {
        QSharedPointer<QPluginLoader> spLoader = m_mapLoaders.value(strPluginName);
        if (!spLoader.isNull())
        {
            T *pPlugin = qobject_cast<T *>(spLoader->instance());
            return pPlugin;
        }
        return nullptr;
    }

private:
    /**
     * @brief scan      扫描json文件中的插件元数据
     * @param strFile   插件路径
     */
    void scan(const QString &strFile);

    /**
     * @brief getAllPluginFileName 获取所有插件路径
     */
    QFileInfoList getAllPluginFileName();

public slots:
    /**
     * @brief recMsgfromPlugin 接收来自各插件的消息
     */
    void recMsgfromPlugin(PluginMetaData metadata);

private:
    static CpePluginManager *m_pInstance;
    CpePluginManager();

    QHash<QString, QString> m_mapNames;                         //插件名称--插件完整路径
    QHash<QString, QString> m_mapVersions;                      //插件名称--插件版本
    QHash<QString, QVariantList> m_mapDependencies;             //插件名称--插件依赖
    QHash<QString, QVariantList> m_mapConDependencies;          //插件名称--插件反依赖
    QHash<QString, QSharedPointer<QPluginLoader>> m_mapLoaders; //插件名称--QPluginLoader实例
    QHash<QString, QString> m_mapDescriptions;                  //插件名称--插件描述
    QHash<QString, QString> m_mapAuthors;                       //插件名称--插件作者
    QHash<QString, bool> m_mapTypes;                            //插件名称--是否必选
};

#define g_pCpePluginManager CpePluginManager::getInstance()

#endif
